package com.bkm;

import com.bkm.factory.BaoKeMeng;
import com.bkm.factory.BaoKeMengFactory;
import com.bkm.factory.TypeEnum;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class StartMain {

    /**
     * 按照海洋/天空/陸地分類
     */
    public static Map<TypeEnum, List<BaoKeMeng>> typeOfBaoKeMeng = new HashMap<>();

    public static void main(String[] args) {
        // 創建所有的寶可夢
        List<BaoKeMeng> baoKeMeng = BaoKeMengFactory.createBaoKeMeng();

        // 根據寶可夢的生日，劃分屬性
        for (BaoKeMeng keMeng : baoKeMeng) {
            typeOfBaoKeMeng = baoKeMeng.stream().collect(Collectors.groupingBy(BaoKeMeng::getType));
        }

        // 開始提問，問生日
        Scanner scanner = new Scanner(System.in);

        // 1.在玩一次, 999.退出
        String finalCode = "y";

        while ("y".equals(finalCode)) {
            TypeEnum typeEnum = input("請輸入生日: ", scanner, (input) -> {
                if (!input.matches("\\d{2}-\\d{2}")) {
                    System.err.println("生日輸入錯誤，請重新輸出有效的生日，如輸入 11-11！");
                    return null;
                }
                TypeEnum type = TypeEnum.typeOf(input);
                if (type == null) {
                    System.err.println("生日輸入錯誤，請重新輸出有效的生日，如輸入 11-11！");
                }
                return type;
            });
            System.out.println("屬於: " + typeEnum.getTypeName());

            // 獲取這個生日的所有寶可夢
            List<BaoKeMeng> baoKeMengs = typeOfBaoKeMeng.get(typeEnum);

            // 最大標簽長度, 為詢問問題的次數
            List<String> select = new ArrayList<>();
            String lastAnswer = null;
            int questionNum = 0;
            while (true){
                List<String> question = getQuestion(baoKeMengs, questionNum, lastAnswer);
                // 上次的回答沒有問題, 表示問答結束
                if (question.isEmpty()) {
                    break;
                }

                StringBuilder questionInput = new StringBuilder();
                for (int j = 0; j < question.size(); j++) {
                    String index = j + 1 + ".";
                    questionInput.append(index + question.get(j) + "   ");
                }

                //獲取回答的下標
                Integer answerIndex = input("請選擇符合自己個性的選項：\n" + questionInput.toString() + "\n", scanner, (input) -> {
                    Integer index = null;
                    try {
                        index = Integer.parseInt(input);
                        if (index > 0 && index <= question.size()) {
                            return index;
                        }
                    } catch (Exception e) {
                    }
                    System.err.println("輸入錯誤，請重新輸入！");
                    return null;
                });

                // 拼接問答路徑
                lastAnswer = question.get(answerIndex - 1);
                select.add(lastAnswer);
                questionNum++;
            }

            // 循環結束, 表示問題回答完畢, 根據回答的問題, 找到寶可夢
            String answerPath = String.join(",", select);

            BaoKeMeng guess = null;
            for (BaoKeMeng keMeng : baoKeMengs) {
                if (keMeng.belongMe(answerPath)) {
                    guess = keMeng;
                    break;
                }
            }
            System.out.println("测出的结果是：");
            System.out.println(guess.getName() + " " + guess.getIntroduce());

            finalCode = input("請問是否要再玩一次呢！（输入y or n）\n", scanner, (input) -> {
                if ("y".equals(input) || "n".equals(input)) {
                    return input;
                } else {
                    System.err.println("輸入錯誤，請重新輸入！");
                    return null;
                }
            });
        }

        System.out.println("系統退出!");
        scanner.close();
    }

    public static <R> R input(String message, Scanner scanner, Function<String, R> flag) {
        System.out.print(message);
        while (scanner.hasNext()) {
            String next = scanner.next();
            if (next == null || next.trim().length() == 0) {
                System.err.println("輸入錯誤，請重新輸入！");
                // 休眠100, 爲了讓控制臺顯示正確
                safeSleep(100);
                System.out.print(message);
                continue;
            }
            if (flag != null) {
                R result = flag.apply(next);
                if (result != null) {
                    return result;
                }

                // 休眠100, 爲了讓控制臺顯示正確
                safeSleep(100);
                System.out.print(message);
            }
        }
        return null;
    }

    /**
     * 獲取對應位置的標簽
     *
     * @param baoKeMengs
     * @return
     */
    public static List<String> getQuestion(List<BaoKeMeng> baoKeMengs, int qNum, String lastAnswer) {
        Set<String> questions = new HashSet<>();
        for (BaoKeMeng baoKeMeng : baoKeMengs) {
            List<String> tags = baoKeMeng.getTags();
            if (tags.size() <= qNum) {
                continue;
            }
            // 如果上次回答存在, 只獲取和上次回答相關的標簽
            if (lastAnswer != null) {
                String beforeTag = tags.get(qNum - 1);
                String[] beforeTagArray = beforeTag.split("\\|");
                for (String tag : beforeTagArray) {
                    if (tag.equals(lastAnswer)) {
                        String currTags  = tags.get(qNum);
                        for (String currTag : currTags.split("\\|")) {
                            questions.add(currTag);
                        }
                        break;
                    }
                }
            } else {
                questions.add(tags.get(qNum));
            }
        }
        return new ArrayList<>(questions);
    }

    /**
     * 安全休眠
     *
     * @param time
     */
    public static void safeSleep(long time) {
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
